package com.yuzhihao.writejvm.attributes.stack;

import com.yuzhihao.writejvm.attributes.Attributes;
import com.yuzhihao.writejvm.clazz.ClassInfo;
import com.yuzhihao.writejvm.format.PrintFormat;
import com.yuzhihao.writejvm.read.Parse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.log4j.Log4j2;

import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 属性
 * <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4">StackMapTableAttribute</a>
 *
 * @author yzh
 * @since 2021年12月10日17:40:24
 */
@Data
@Log4j2
@EqualsAndHashCode(callSuper = true)
public class StackMapTableAttribute extends Attributes {

    private int number_of_entries_2 = 2;

    private int number_of_entries;

    private List<StackMapFrame> frames = new ArrayList<>();

    public StackMapTableAttribute(String name){
        super();
        super.setAttribute_name(name);
    }

    @Override
    public void parse(DataInputStream dis, ClassInfo ci) {
        try {
            super.attribute_length = Parse.byteToInt(super.attribute_length_u4, dis);
            this.number_of_entries = Parse.byteToInt(this.number_of_entries_2, dis);

            if(this.number_of_entries > 0){
                StackMapFrame frame = new StackMapFrame(this.number_of_entries);
                frame.parse(dis, ci);
                this.setFrames(frame.frames);
            }

        } catch (IOException e) {
            log.error(e);
        }
    }

    @Override
    public String print(String print) {
        StringBuilder builder = new StringBuilder();
        builder.append(print)
                .append("StackMapTable")
                .append(PrintFormat.COLON)
                .append(PrintFormat.EMPTY)
                .append("number_of_entries")
                .append(PrintFormat.EQUAL)
                .append(this.number_of_entries)
                .append(System.lineSeparator());

        if(this.number_of_entries > 0){
            for (StackMapFrame frame : this.frames) {
                builder.append(frame.print(print+PrintFormat.EMPTY));
            }
        }

        return builder.toString();
    }
}
